import sys


class Domain:
    """
    Contains dictionaries of elements and nodes which describe
    the problem domain.
    """

    def __init__(self):
        self.current_time = 0.0
        self.elements = {}
        self.nodes = {}
        self.sp_constraints = {}
        self.number_of_sp_constraints = 0

        self.has_domain_changed = False

    def add_element(self, element, check=False):
        """
        Adds an element object to the domain.  If check is set to true, then
        verify that all of the node objects associated with the element
        exist in the domain.
        """
        if check:
            for node in element.element_nodes:
                if not node.node_id in self.nodes:
                    print >> sys.stderr, "Error: cannot add element\nNode " \
                      + str(node.node_id) + " is not in this domain"
                    return False

        self.elements[element.element_id] = element
        return True

    def add_node(self, node, check=False):
        """
        Adds a node object to the domain.  If check is set to True, then verify
        that we're not overwriting an existing node object.
        """
        if check:
            if node.node_id in self.nodes:
                print >> sys.stderr, "Warning - A node with node id: " \
                                     + str(node.node_id) + " already " \
                                     + " exists in the domain."
                return False
        self.nodes[node.node_id] = node
        return True

    def add_sp_constraint(self, sp_constraint, check=False):
        if check:
            if not sp_constraint.node.node_id in self.nodes:
                print >> sys.stderr, "Error: cannot add sp_constraint\nNode " \
                  + str(sp_constraint.node_id) + " is not in this domain"
                return False
        self.sp_constraints[sp_constraint.constraint_id] = sp_constraint
        return True

    def draw_elements(self):
        from numpy import array
        fig = figure()
        ax = fig.add_subplot(111)
        return None

    def draw_nodes(self):
        """
        Creates an image file that illustrates the location of all of the
        nodes in the domain.
        """
        from matplotlib.pyplot import plot, savefig, figure, show, grid
        xdata = []
        ydata = []
        fig = figure()
        ax = fig.add_subplot(111)
        for node_id in self.nodes:
            x = self.nodes[node_id].coordinates[0]
            y = self.nodes[node_id].coordinates[1]
            xdata.append(x)
            ydata.append(y)
            ax.annotate(str(node_id), xy=(x, y),  xycoords='data')

        ax.plot(xdata, ydata, 'o')
        ax.set_xlim(min(xdata) - 0.25, max(xdata) + 0.25)
        ax.set_ylim(min(ydata) - 0.25, max(ydata) + 0.25)
        grid()
        show()
        savefig('nodes.png')

    def remove_element(self, element_id):
        """
        Removes an element object from the domain.
        """
        if element_id in self.elements:
            del self.elements[element_id]
        else:
            print >> sys.stderr, "Error: Cannot remove element " \
                                + str(element_id) + " from domain.\n \
                                This element does not exist."
            sys.exit(1)

    def remove_node(self, node_id):
        """
        Removes a node object from the domain.
        """
        if node_id in self.nodes:
            del self.nodes[node_id]
        else:
            print >> sys.stderr, "Error: Cannot remove node "
            + str(node_id) + " from domain.\nThis node does not exist."
            sys.exit(1)
